//
// Created by yuhaibo on 18-11-16.
//

//#ifndef ANDROID_OTA_H
//#define ANDROID_OTA_H
#ifndef VENDOR_ECARX_OTA_V1_0_OTA_H
#define VENDOR_ECARX_OTA_V1_0_OTA_H

#include <android-base/properties.h>
#include <WorkerThread.h>
#include <ipcp/ipcp.h>
#include <log/log.h>
#include <vendor/ecarx/xma/ota/1.0/IOta.h>
#include <vendor/ecarx/xma/ota/1.0/IOtaClientCallback.h>
#include <vendor/ecarx/xma/ota/1.0/types.h>
// #include <vendor/ecarx/xma/dtcnl/1.0/IDtcnl.h>

namespace vendor {
namespace ecarx {
namespace xma {
namespace ota {
namespace V1_0 {

using std::lock_guard;
using std::mutex;
using std::chrono::milliseconds;
using std::chrono_literals::operator""ms;
using ::android::sp;
using ::android::wp;
using ::android::hardware::hidl_death_recipient;
using ::android::hardware::hidl_string;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::vendor::ecarx::xma::ota::V1_0::Languages;
// using ::vendor::ecarx::xma::dtcnl::V1_0::IDtcnl;

#define OTA_IPCP_VERSION 13
//-----------------------------------------------------------
// for ota_test
// local
#define TEST_LOCAL_IP "127.0.0.1"
#define TEST_LOCAL_PORT 8888
#define TEST_VLAN_ID 0
#define TEST_VLAN_PRIORITY 0
// remote
#define TEST_SERVICE_IP "127.0.0.1"
#define TEST_SERVICE_PORT 6666
#define TEST_MODE 1
//-----------------------------------------------------------
// for OTA
#define LOCAL_IP "198.18.34.15"
#define LOCAL_PORT 50171

#define PEER_IP "198.18.32.17"
#define PEER_PORT 50171

#define PEER_VGM_IP "198.18.32.1"
#define PEER_VGM_PORT 50171

#define SERVICE_ID 0xAB
#define VLAN 2
#define PRIORITY 0
#define OTA_MODE 0
//------------------------------------------------------------

#define OP_TYPE_REQUEST 0x00
#define OP_TYPE_RESPONSE 0x04
#define OP_TYPE_NOTIFICATION 0x05
#define OP_TYPE_ERROR 0xE0

// Define Service ID
#define SERVICE_ID_OTA 0xAB

// Define Operation Type
#define OP_ID_DOWNLOAD_CONSENT 0x0B19
#define OP_ID_INSTALLATION_CONSENT 0x0B20
#define OP_ID_USER_OTA_SETTINGS 0x0B21
#define OP_ID_OTA_ASSIGNMENT_SYNC 0x0B22
#define OP_ID_OTA_TCAM_ASSIGNMENT_NOTIFICATION 0x0B24
#define OP_ID_OTA_DOWNLOAD_PROGRESS 0x0B25
#define OP_ID_OTA_HMI_LANGUAGESETTINGS 0x0B51
#define OP_ID_CONNECTIVITY_STATUS 0x0B52
#define OP_ID_APP_INSTALL_CONSENT 0x0B56
#define OP_ID_SYNC_SCH_INSTALL_TIME 0x0B57
#define OP_ID_OTA_INSTALLATION_REGRET_TIMEOUT 0x0B59
#define OP_ID_BSSID_DISPLAYEDVERSION_SYNC 0x0B60

#define OP_ID_OTA_DOWNLOAD_STATUS 0x0B61
#define OP_ID_OTA_ASSIGNMENT_KEY_TO_TARGET_ECU 0x0B62 
#define OP_ID_OTA_URL_INFO 0x0B64

#define OP_ID_OTA_SIGNATURE_CERTIFICATE 0x0B55
#define OP_ID_OTA_EXCEPTION_REPORTS 0x0B28
#define OP_ID_OTA_WRITE_INSTALLATION_INSTRUCTION 0x0B16
#define OP_ID_OTA_SET_ASSIGNMENT_FILE_INFO 0x0B29
#define OP_ID_OTA_POST_INSTALLATION 0x0B72

#define OP_ID_RVDC_LOG_TRANSFER_RETRY 0x0BE0
#define OP_ID_RVDC_TRANSFER_LOGS_CRC 0x0BE1
#define OP_ID_RVDC_VERIFICATION_CRC_STATUS 0x0BE2
#define OP_ID_RVDC_TRANSFER_LOGS_DATA 0x0BE3

#define OTA_SETTING "persist.vendor.ota.setting"
#define OTA_AUTO_SYNC "persist.vendor.ota.auto.sync"
#define OTA_AUTO_DOWNLOAD "persist.vendor.ota.auto.download"
#define OTA_AUTO_INSTALL "persist.vendor.ota.auto.install"

#define ASN_HEADER_LENGTH_OFFSET 8

typedef void (*ota_callback)(int status);

class Ota : public IOta {
  public:
    Ota();

    ~Ota();

    virtual void onFirstRef();

    Return<StatusCode> init_ota_ipcp() override;

    Return<StatusCode> requestOTAAssignment() override;

    Return<StatusCode> requestSyncSchInstallTime() override;

    Return<StatusCode> setDownloadConsent(const hidl_string& installationorder,
                                          bool downloadconsent) override;

    Return<StatusCode> setUserOtaSettings(const OpOTAUserOtaSettingsHal&
                                          opOTAUserOtaSettingsHal) override;

    Return<StatusCode> buildUserOtaSettingsTest(const OpOTAUserOtaSettingsHal&
                                          opOTAUserOtaSettingsHal) override;

    Return<StatusCode> setInstallationConsent(const hidl_string& installationorder,
                                              InstallationConsent installationConsent,
                                              int deltatime) override;

    Return<StatusCode> requestBSSIDDisplayedVersionSync() override;

    Return<StatusCode> setOTAInstallationRegretTimeOut(const OpOTAInstallationRegretTimeOutHal& opOTAInstallationRegretTimeOutHal) override;

    Return<StatusCode> setOTAHMILanguageSettings(Languages languages) override;

    Return<StatusCode> setOTADownloadStatusHal(const OpOTADownloadStatusHal& opOTADownloadStatusHal) override;

    Return<StatusCode> setAssignmentkeytoTargetECUResHal(const OpAssignmentkeytoTargetECUHal& opAssignmentkeytoTargetECUHal) override;

    Return<StatusCode> setOTAExceptionReportsHal(const OpOTAExceptionReportsHal& opOTAExceptionReportsHal) override;

    Return<StatusCode> setOTAURLInfoResHal(const hidl_string& status) override;

    Return<StatusCode> setSignatureCertificateResHal(const hidl_string& chkResponse) override;

    Return<StatusCode> setWriteInstallationInstructionResHal(const hidl_string& chkResponse) override;

    Return<StatusCode> setAssignmentFileInfoResHal(const hidl_string& chkResponse) override;

    Return<StatusCode> setRVDCTransferLogsCRCResHal(const hidl_string& name, const hidl_string& status) override;

    Return<StatusCode> setRVDCVerificationCRCStatusHal(const hidl_string& name, bool verificationok) override;

    Return<StatusCode> setRVDCTransLogDataResHal(const TransRVDCLogDataResponse& response) override;

    Return<StatusCode> setRVDCLogInterruptedDataTransferRetryResHal(int filesize) override;

    Return<StatusCode> requestOTAConnectivitySts() override;

    Return<StatusCode> subscribe(const ::android::sp<IOtaClientCallback>& callback) override;

    Return<StatusCode> unsubscribe(const ::android::sp<IOtaClientCallback>& callback) override;

    int bytesToInt(u_int8_t* bytes);
    Return<bool> getVerifySignatureStatus() override;

    static sp<Ota> getOta(void* cookie);

    sp<IOtaClientCallback> getCallback();

    //-------------------------- ota test --------------------------

    Return<StatusCode> init_ota_ipcp_test();

    Return<StatusCode> buildInstallationConsentTest(const hidl_string& installationorder,
                                                    InstallationConsent installationConsent,
                                                    int deltatime) override;

    Return<StatusCode> buildOTAHMILanguageSettingsTest(Languages languages) override;

    Return<StatusCode> buildOTAPacketTest(const OpOTAAssignmentParamHal& opOTAAssignmentParamHal) override;

    Return<StatusCode> buildOTATCAMPacketTest(const OpOTATCAMAssignmentParamHal& opOTATCAMAssignmentParamHal) override;

    Return<StatusCode> buildPostInstallationTest(const OpOTAPostInstallationParamHal& opOTAPostInstallationParamHal) override;

    Return<StatusCode> buildOTAConnectivityStsTest(const ConnectivityStsHal& conSts) override;

    Return<StatusCode> buildOTAAPPInstallationConsentTest(const APPInstallationConsentHal& appInsConsent) override;

    Return<StatusCode> buildOTASyncSchInstallTimeTest(const SyncSchInstallTimeHal& syncInsTime) override;

    Return<StatusCode> buildBSSIDDisplayedVersionTest(const OpBSSIDDisplayedVersionSyncHal& opBSSIDDisplayedVersionSyncHal) override;

    Return<StatusCode> buildWriteInstallationInstructionTest(const OpOTAWriteInstallationInstructionHal& opOTAWriteInstallationInstructionHal) override;

    Return<StatusCode> buildAssignmentFileInfoTest(const OpOTASetAssignmentFileInfoHal& opOTASetAssignmentFileInfoHal) override;

    Return<StatusCode> buildURLInfoTest(const OpOTAURLInfoReqHal& opOTAURLInfoReqHal) override;

    Return<StatusCode> buildAssignmentkeytoTargetECUTest(const OpAssignmentkeytoTargetECUHal& opAssignmentkeytoTargetECUHal) override;

    Return<StatusCode> buildSignatureCertificateTest(const hidl_string& param) override;

    Return<StatusCode> buildDownloadProgressNotificationTest(DownloadProgress progress) override;

    Return<StatusCode> buildRVDCTransferLogsCRCTest(const hidl_string& logname, const hidl_string& logcrc) override;

    Return<StatusCode> buildRVDCLogInterruptedDataTransferRetryTest(const hidl_string& logname) override;

    void handleHidlDeath();

    // void setupDtcnl();
    // void reportDtc();

  private:
    class DeathRecipient : public hidl_death_recipient {
      public:
        DeathRecipient(sp<Ota> ota) : mOta(ota) {}
        ~DeathRecipient() = default;
        virtual void serviceDied(uint64_t cookie /*cookie*/,
                                 const wp<android::hidl::base::V1_0::IBase>& /*who*/) {
            ALOGD("function: %s, service %lu", __func__, cookie);
            mOta->handleHidlDeath();
        }

      private:
        sp<Ota> mOta;
    };

    //-------------------------- ota test --------------------------
  private:
    mutex mMut;
    sp<IOtaClientCallback> mCallback;
    WorkerThread mThread;

    static ota_callback gOtaCallback;
    sp<DeathRecipient> mCallbackDeathRecipient;
    // sp<IDtcnl> mDtcnl;
};

// } // namespace implementation
}  // namespace V1_0
}  // namespace ota
}  // namespace xma
}  // namespace ecarx
}  // namespace vendor
#endif  // VENDOR_ECARX_OTA_V1_0_OTA_H
